package com.ybf.api.websocket;

import com.ybf.api.entity.WsMessage;
import com.ybf.api.entity.WsUser;
import com.ybf.api.utils.Utils;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Component
@ServerEndpoint("/ws")
@Slf4j
public class WebSocketServer {

    private static final Set<WsUser> wsUserList = Collections.synchronizedSet(new HashSet<>());
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public WebSocketServer() {
        // 启动心跳任务
        scheduler.scheduleAtFixedRate(WebSocketServer::checkAlive, 0, 26, TimeUnit.SECONDS);
    }

    @OnOpen
    public void onOpen(Session session) throws UnsupportedEncodingException {

        // 获取查询参数
        Map<String, String> queryParams = Utils.parseQuery(session.getQueryString());
        log.info("New connection opened with query params: {}", queryParams);
        // 获取 userId 和 groupId
        String userId = queryParams.get("userId");
        String groupId = queryParams.get("groupId");

        if (userId == null || groupId == null) {
            try {
                // 如果 userId 或 groupId 缺失，关闭连接
                session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "Missing userId or groupId"));
            } catch (IOException e) {
                log.error("Failed to close session due to missing userId or groupId", e);
            }
            return;
        }

        WsUser wsUser = new WsUser();
        wsUser.setUserId(Integer.parseInt(userId));
        wsUser.setGroupId(groupId);
        wsUser.updateLinkTimeout();
        wsUser.setSession(session);

//        // 验证 userId 和 groupId（根据你的业务逻辑）
//        boolean isValid = validateUserAndGroup(userId, groupId);
//        if (!isValid) {
//            try {
//                // 如果验证失败，关闭连接
//                session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "Invalid userId or groupId"));
//            } catch (IOException e) {
//                log.error("Failed to close session due to invalid userId or groupId", e);
//            }
//            return;
//        }
        wsUserList.add(wsUser);
        log.info("新的连接已打开，userId: {}, groupId: {}", userId, groupId);
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        // message的json字符串转对象
        WsMessage msg = (WsMessage) Utils.jsonToObject(message, WsMessage.class);

        // 处理接收到的消息
        log.info("收到client消息：{}", message);

        for (WsUser wsUser : wsUserList) {
            if (wsUser.getGroupId().equals(message)) {
                wsUser.updateLinkTimeout();
                break;
            }
        }

        // 处理心跳响应
        if (WsMessage.HEARTBEAT.equals(msg.getType())) {
            System.out.println("收到心跳");
            WebSocketServer.sendMessage(session, WsMessage.Heartbeat());
        }
    }

    @OnClose
    public void onClose(Session session) {
        // wsUserList中删除session对应的wsUser
        for (WsUser wsUser : wsUserList) {
            if (wsUser.getSession().equals(session)) {
                wsUserList.remove(wsUser);
                break;
            }
        }
    }

//    @OnError
//    public void onError(Throwable t) {
//        System.out.println("WebSocket error: " + t.getMessage());
//    }

    private static void checkAlive() {
        synchronized (wsUserList) {
            log.info("-----checkAlive-----:" + System.currentTimeMillis());
            for (WsUser wsUser : wsUserList) {
                Session session = wsUser.getSession();
                long linkTimeout = System.currentTimeMillis() - wsUser.getLinkTimeout();
                log.info("userId: " + wsUser.getUserId() + ", linkTimeout: " + linkTimeout);
                if (session.isOpen() && linkTimeout > 0) {
                    try {
                        session.close();
                        wsUserList.remove(wsUser);
                        log.warn("userId: " + wsUser.getUserId() + ": - 心跳断开");
                    } catch (IOException e) {
                        log.warn("心跳断开: " + e.getMessage());
                    }
                }
            }
        }
    }

    public static void sendMessage(WsMessage wsMessage) {
        if (wsMessage.isEmpty()) {
            log.info("message is empty");
            return;
        }
        for (WsUser wsUser : wsUserList) {
            Session session = wsUser.getSession();
            if (session.isOpen()) {
                session.getAsyncRemote().sendText(wsMessage.toString());
            }
        }
    }

    public static void sendMessage(Session session, WsMessage wsMessage) {
        // 判断session是否为空
        if (session == null || wsMessage.isEmpty()) {
            log.info("session or message is empty");
            return;
        }
        if (session.isOpen()) {
            try {
                session.getBasicRemote().sendText(wsMessage.toString());
            } catch (IOException e) {
                log.error("send message error: " + e.getMessage());
            }
        }
    }

    public static void sendMessage(String groupId, WsMessage wsMessage) {
        if (groupId.isEmpty() || wsMessage.isEmpty()) {
            log.info("groupId or message is empty");
            return;
        }
        for (WsUser wsUser : wsUserList) {
            if (wsUser.getUserId().equals(groupId)) {
                continue;
            }
            Session session = wsUser.getSession();
            WebSocketServer.sendMessage(session, wsMessage);
        }
    }
}
